use std::{
    cmp::Reverse,
    collections::HashMap,
    fs::{self, Metadata},
};

use color_eyre::owo_colors::OwoColorize;
use futures::{FutureExt, TryFutureExt};
use itertools::Itertools;
use walkdir::WalkDir;

pub fn stats_code(project_path: &str) -> Vec<(String, u64)> {
    let mut es: Vec<(String, u64)> = WalkDir::new(project_path)
        .sort_by_file_name()
        .follow_links(true)
        .into_iter()
        .filter_map(|entry| {
            if let Ok(path) = entry {
                let full_path: String = path.path().display().to_string();
                if let Some(extension) = path.path().extension() {
                    let extension_suffix: String = extension.to_string_lossy().to_string();
                    let file_size = fs::metadata(full_path)
                        .ok()
                        .map(|item| item.len())
                        .unwrap_or(0 as u64);
                    return Some((extension_suffix, file_size));
                }
            }
            return None;
        })
        .fold(HashMap::new(), |mut acc, (k, v)| {
            *acc.entry(k).or_insert(0) += v;
            acc
        })
        .into_iter()
        .collect();

    //
    es.sort_by_key(|&(ref k, v)| Reverse(v));

    return es;
}

#[test]
fn test_stats_code() {
    //
    let suffix_list: Vec<&str> = vec!["go", "java", "js", "rs"];

    let es: Vec<(String, u64)> = stats_code(".");
    let es: Vec<(String, u64)> = es
        .into_iter()
        .filter(|(suffix, file_size)| {
            if suffix_list.contains(&suffix.as_str()) {
                return true;
            }
            return false;
        })
        .collect();

    //
    let total_size: u64 = es.iter().fold(0u64, |mut acc, (k, v)| {
        acc += v;
        acc
    });

    println!("total size: {total_size}");

    for (suffix, size) in es.iter() {
        println!("{suffix}\t{size}");
    }
}
